package mapSystem;

import java.awt.image.BufferedImage;
import java.util.*;

import tools.*;

import levelSystem.*;
import mapSystem.interaction.TileAction;

public class MapHandler {

	private MapLevel owner;
	private GameMap gameMap;
	private ArrayList<GameElement> elements;
	
    private ArrayList<Tile> showingTiles;
    private ArrayList<Tile> showingWalls;
    	
	public MapHandler(MapLevel level) {
	
		owner = level;
		gameMap = new GameMap(this);
		elements = new ArrayList<GameElement>();
		
		showingTiles = new ArrayList<Tile>();
		showingWalls = new ArrayList<Tile>();
	}
	
	public void addElement(GameElement e)
	{
		elements.add(e);
	}
	public void checkEvents(int x, int y, int type)
	{
		GameElement e = null;
		if(type == 1) // auto activate
		{
			e = gameMap.autoActivate(x, y);
		}else if(type == 2) // player activated
		{
			e = gameMap.playerActivated(x, y);
			if(e != null && e.getID() < 5) owner.playButton();
		}
		/* actions activate other actions in most cases */
		while(e != null && e.getID() == 1) // 
		{
			e = gameMap.autoActivate((int)e.getRect().x,(int)e.getRect().y);
		}
		while(e != null && (e.getID() == 3 || e.getID() == 4)) // action hides/show action if ID = 3
		{
			if(gameMap.getActions()[(int)e.getRect().x][(int)e.getRect().y] != null)
			{
				if(e.getID() == 3) gameMap.getActions()[(int)e.getRect().x][(int)e.getRect().y].changeVisible();
				e = gameMap.getActions()[(int)e.getRect().x][(int)e.getRect().y].simpleActivate();
			}else e = null;
		}
		while(e != null && e.getID() == 2) // action hides/show action and change tile access
		{
			x = (int)e.getRect().x;
			y = (int)e.getRect().y;
			if(gameMap.getBaseMap()[x][y].getType() == 0)
				gameMap.getBaseMap()[x][y].setType(1);
			else gameMap.getBaseMap()[x][y].setType(0);
			if(gameMap.getActions()[x][y] != null)
			{
				gameMap.getActions()[x][y].changeVisible();
				e = gameMap.getActions()[x][y].simpleActivate();
				if(e.getRect().x == x && e.getRect().y == y) e = null;
			}else e = null;
		}
		if(e != null)
		{
			addElement(e);
		}
		if(type == 2) checkElements(x, y);
	}	
	private void checkElements(int x, int y) {
		int xe = -1;
		int ye = -1;
		
		for(int i = 0; i < elements.size(); i++)
		{
			xe = (int) elements.get(i).getRect().x/Constants.TILE_WIDTH;
			ye = (int) elements.get(i).getRect().y/Constants.TILE_HEIGHT;
			if(elements.get(i).getID() > 4 && x == xe && y == ye)
			{
				owner.equipChar(elements.get(i).getID());
				elements.remove(i);
				i = elements.size();
			}
		}
	}

	public void forceChangeLevel(String mapName, int x, int y)
	{
		owner.setCharPosition(x, y);
		
		MapLoader.load(mapName, gameMap);
		if(gameMap.getBaseMap() == null) owner.error();
		else if(mapName != null) // map changed
		{
			owner.mapChanged();
			
			elements.clear();
			showingTiles.clear();
			showingWalls.clear();
			
			owner.calcValues();
			owner.getGame().saveGame(mapName, x, y);
		}
		
	}
	public void changeLevel(String mapName, int x, int y)
	{
		int xt = 0;
		int yt = 0;
		
		if(gameMap != null && gameMap.hasPortals())
		{			
			xt = gameMap.getPortalCoord(x, y).x;
			yt = gameMap.getPortalCoord(x, y).y;

			if(xt > 0 && yt > 0) owner.setCharPosition(xt, yt);
		}
		
		MapLoader.load(mapName, gameMap);
		if(gameMap.getBaseMap() == null) owner.error();
		else if(mapName != null) // map changed
		{
			owner.mapChanged();
			
			elements.clear();
			showingTiles.clear();
			showingWalls.clear();
			
			owner.calcValues();
			owner.getGame().saveGame(mapName, xt, yt);
		}
	}
	
	public void setShowingTiles(Rect cam)
	{
		for(int i = 0; i < getMapWidth(); i++)
        {
            for(int j = 0; j < getMapHeight(); j++)
            {
                if(Physics.checkBlockCollision(cam, gameMap.getBaseMap()[i][j].getRect()))
                {
                    showingTiles.add(gameMap.getBaseMap()[i][j]);
                    if(gameMap.getBaseMap()[i][j].getType() == 0) 
                    {
                    	showingWalls.add(gameMap.getBaseMap()[i][j]);
                    }
                }
            }
        }
	}
	public ArrayList<Tile> getShowingWalls()
	{
		return showingWalls;
	}
	public ArrayList<Tile> getShowingTiles()
	{
		return showingTiles;
	}

	
	public Tile[][] getBaseMap()
	{
		return gameMap.getBaseMap();
	}
	public BufferedImage[][] getOvermap()
	{
		return gameMap.getOverMap();
	}
	
	public boolean mapIsNull() {
		return gameMap == null;
	}

	public int getMapWidth() {
		if(gameMap.getBaseMap() != null) return gameMap.getBaseMap().length;
		return 0;
	}
	public int getMapHeight() {
		if(gameMap.getBaseMap() != null) return gameMap.getBaseMap()[0].length;
		return 0;
	}

	public void clearShowingTiles() {
        showingTiles.clear();
        showingWalls.clear();		
	}
	
	public ArrayList<GameElement> getElements()
	{
		return elements;
	}
	
	public TileAction[][] getActions()
	{
		return gameMap.getActions();
	}
}